﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

using DocumentFormat.OpenXml.Wordprocessing;

using ProjectBase.Core;

namespace $safeprojectname$.Export.Word
{
    public static partial class Ext
    {
        public static bool TryGetResult<T, TResult>(this T item, string propertyName, out TResult result)
            where T : class, IPersistentObject
            where TResult : class
        {
            var split = propertyName.Split('.');
            if (split.Length > 1)
            {
                IPersistentObject entity;
                if (GetPropertyValue(item, split[0], out entity))
                {
                    return TryGetResult(entity, propertyName.Substring(split[0].Length + 1), out result);
                }
                result = null;
                return false;
            }
            return GetPropertyValue(item, propertyName, out result);
        }

        public static bool GetPropertyValue<T, TResult>(this T item, string propertyName, out TResult result)
            where T : class
        {
            result = default(TResult);
            if (item.IsNull())
            {
                return false;
            }

            var type = item.GetType();

            var param = Expression.Parameter(typeof(object)); // param for FUNC
            var parameterName = Expression.Parameter(typeof(string));
            var parameterEntity = Expression.Convert(param, type); // converted param for Property expression

            try
            {
                var getPropertyValue = Expression.Property(parameterEntity, type, propertyName);
                var lambda = Expression.Lambda<Func<object, string, TResult>>(
                    Expression.Convert(getPropertyValue, typeof(TResult)), param, parameterName);
                result = lambda.Compile().Invoke(item, propertyName);
            }
            catch (Exception)
            {
                return false;
            }
            return result.Is();
        }

        public static void InjectValue(this DocPart part, string text)
        {
            Contract.Requires(part.Is(), "DocPart part was null, cannot proceed InjectValue()");
            foreach (var t in part.Descendants<Run>().SelectMany(r => r.Elements<Text>()))
            {
                t.Text = string.Empty; // clear all texts
            }

            var run = part.Descendants<Run>().FirstOrDefault()
                      ?? part.AppendChild(new Run());

            var txt = run.Elements<Text>().FirstOrDefault()
                      ?? run.AppendChild(new Text());

            txt.Text = text ?? string.Empty;
            part.RestoreElements();
        }

        public static void RepeatValues(this DocPart part, System.Collections.IEnumerable values)
        {
            Contract.Requires(part.Is(), "DocPart part was null, cannot proceed RepeatValue()");
            Contract.Requires(values.Is(), "IEnumerable values was null, cannot proceed RepeatValue()");

            var list = values.Cast<object>();

            for (var i = 0; i < list.Count(); i++)
            {
                var item = part.CreateTextElement(list.ElementAt(i).ToDisplay(), ((i + 1) == list.Count()));
                part.InsertBeforeSelf(item);
                item.RestoreElements();
            }

            part.Remove();
        }
    }
}